package com.xuzmian.demo.kotlin

import java.awt.event.MouseAdapter
import java.awt.event.MouseEvent

/**
 * 继承自某个（或某些）类型的匿名类的对象:
 */
var customMouseAdapter: MouseAdapter = object : MouseAdapter() {
    override fun mouseClicked(e: MouseEvent) { /*……*/
    }

    override fun mouseEntered(e: MouseEvent) { /*……*/
    }
}

/**
 * 只需要“一个对象而已”，并不需要特殊超类型，可以简单地写:
 */
fun Objectsfoo() {
    val adHoc = object {
        var x: Int = 0
        var y: Int = 0
    }
    print(adHoc.x + adHoc.y)
}


/**
 * 如果超类型有一个构造函数，则必须传递适当的构造函数参数给它。 多个超类型可以由跟在冒号后面的逗号分隔的列表指定：
 */
open class A(x: Int) {
    public open val y: Int = x
}

interface B { /*……*/ }

val ab: A = object : A(1), B {
    override val y = 15
}

/**
 * 匿名对象可以用作只在本地和私有作用域中声明的类型。如果你使用匿名对象作为公有函数的返回类型或者用作公有属性的类型，
 * 那么该函数或属性的实际类型会是匿名对象声明的超类型，如果你没有声明任何超类型，就会是 Any。
 */
class C {
    // 私有函数，所以其返回类型是匿名对象类型
    private fun foo() = object {
        val x: String = "x"
    }

    // 公有函数，所以其返回类型是 Any
    fun publicFoo() = object {
        val x: String = "x"
    }

    fun bar() {
        val x1 = foo().x        // 没问题
        // val x2 = publicFoo().x  // 错误：未能解析的引用“x”
    }
}

/**
 * 单例模式：这称为对象声明。在 object 关键字后跟一个名称。 就像变量声明一样，对象声明不是一个表达式，不能用在赋值语句的右边。
 * 对象声明的初始化过程是线程安全的。如需引用该对象，我们直接使用其名称即可：
 * DataProviderManager.registerDataProvider(……)
 *
 * 注意：对象声明不能在局部作用域（即直接嵌套在函数内部），但是它们可以嵌套到其他对象声明或非内部类中。
 */
object DataProviderManager {
    fun registerDataProvider(provider: String) {
        // ……
    }

    val allDataProviders: Collection<Int>
        get()= listOf(1,2,3)
}

/**
 * 伴生对象：类内部的对象声明可以用 companion 关键字标记。kotlin伴生对象看起来类似于java的静态成员，
 * 但，在运行时他们仍然是真实对象的实例成员口。在 JVM 平台，如果使用 @JvmStatic 注解，你可以将伴生对
 * 象的成员生成为真正的静态方法和字段。
 *
 * 下面的伴生对象调用：
 * val instance = MyClass.create()
 */
class TheCompanionClass {
    companion object Factory {
        fun create(): TheCompanionClass = TheCompanionClass()
    }
}

/**
 * 可以省略伴生对象的名称，在这种情况下将使用名称 Companion：
 * val x = TheAnonymousCompanionClass.Companion
 */
class TheAnonymousCompanionClass {
    companion object { }
}


/**
 * 伴生对象可以实现接口。
 * val f: CompanionInterface<TheCompanionImplementInterface> = TheCompanionImplementInterface
 */
interface CompanionInterface<T> {
    fun create(): T
}

class TheCompanionImplementInterface {
    companion object : CompanionInterface<TheCompanionImplementInterface> {
        override fun create(): TheCompanionImplementInterface = TheCompanionImplementInterface()
    }
}
